#ifndef _DBCOMMON_H_
#define	_DBCOMMON_H_

#include <utillib/util/SingleTon.h>
#include <utillib/thread/Thread.h>
#include <utillib/thread/ThreadManager.h>
#include <utillib/io/file.h>
#include <utillib/stl/QueueList.h>
#include <utillib/memory/MemoryPool.h>
#include <utillib/service/WinService.h>
#include <databaselib/io/DataType.h>
#include <databaselib/io/DataBase.h>

namespace databaselib
{
	namespace io
	{
		struct ReleaseAgentDB
		{ 
			template < class _Ty > 
			bool operator( )( const _Ty agentDB ) const 
			{
				if ( agentDB )  agentDB->release();
				return ( true );
			} 
		};

		class AgentDBManager 
		{
		protected:
			AgentDBManager()
			{
			};
		public:
			virtual ~AgentDBManager()
			{
			};
			SingletonInstance( AgentDBManager );

			void insert( AgentDB *agent )
			{
				m_listAgentDB.push( agent );
			};
			void release()
			{
				m_listAgentDB.forEach( ReleaseAgentDB() );
				m_listAgentDB.clear();
			};
			void remove( AgentDB *agent )
			{
				if ( m_listAgentDB.remove( agent ) == true )
					agent->release();
			}
		private :
			utillib::stl::QueueList < AgentDB * > m_listAgentDB;
		};
		class WriteLog 
		{
		public:
			struct QueryPoolElement
			{
				char query[ QUERY_LENGTH ];
			};
		protected:
			WriteLog()
			{
				utillib::thread::ThreadManager::getInstance()->add( new WriteLogThread() );
			};
		public:
			virtual ~WriteLog(){};

			SingletonInstance( WriteLog );

			void put( const char *srcQuery )
			{
				QueryPoolElement *query = m_queryPool.pop();
				SYSTEMTIME currentTime;
				GetLocalTime( &currentTime );

				wsprintf( query->query, "[%02d-%02d %02d:%02d:%02d]:[%s]\r\n", currentTime.wMonth, currentTime.wDay,
					currentTime.wHour, currentTime.wMinute, currentTime.wSecond, srcQuery  );
				m_list.push( query ) ;
			};
			QueryPoolElement *get()
			{
				QueryPoolElement *query = m_list.pop();
				return ( query );
			}
			void push_pool( QueryPoolElement *query )
			{
				m_queryPool.push( query );
			};
		private:
			utillib::stl::QueueList < QueryPoolElement * > m_list;
			utillib::memory::MemoryPool < QueryPoolElement > m_queryPool;


			class WriteLogThread : public utillib::thread::Thread
			{
			public:
				WriteLogThread()
				{
					GetLocalTime( &m_currentTime );
					openFile();
				};
				virtual ~WriteLogThread(){};

				void openFile()
				{
					char filename[ _MAX_PATH ] = { 0 };
					wsprintf( filename, "%s\\QueryLog\\QueryError.%04d_%02d_%02d.log", 
						utillib::service::WinService::getInstance()->getModuleFilePath() ,
						m_currentTime.wYear , m_currentTime.wMonth, m_currentTime.wDay );

					m_file.close();
					m_file.open( filename, utillib::io::File::MODE_WRITE );
					m_file.seek( 0, utillib::io::File::END );
				}
				virtual DWORD run()
				{
					for ( ;; )
					{
						SYSTEMTIME currentTime;
						GetLocalTime( &currentTime );
						if ( currentTime.wDay != m_currentTime.wDay )
						{
							CopyMemory( &m_currentTime, &currentTime, sizeof( SYSTEMTIME ) );
							openFile();
						}

						if ( m_eventThreadStop.wait( 1000 ) == true ) break;

						for ( ;; )
						{
							WriteLog::QueryPoolElement *query = WriteLog::getInstance()->get();
							if ( !query ) break;
							m_file.write( query->query, ( int )strlen( query->query ) );
							WriteLog::getInstance()->push_pool( query );
						}
					}
					return ( 0 );
				}
			private:
				SYSTEMTIME m_currentTime;
				utillib::io::File m_file;
			};

		};
		class SynchronizedDatabase
		{	
		public:
			SynchronizedDatabase( AgentDB *agentDB ) : m_agentDB( agentDB ) , m_database( NULL ){};
			virtual ~SynchronizedDatabase()
			{
				if ( m_database ) m_agentDB->checkDBConnect( m_database );
			};

			Database *getDatabase()
			{
				m_database = m_agentDB->getDataBase();
				return ( m_database );
			};
		private:
			AgentDB *m_agentDB;
			Database *m_database;
		};
	}
}


#endif